﻿using System;
using System.Text;
using System.Security.Cryptography;

namespace DoNet.Utils
{
    /// <summary>
    /// 证书/回调报文解密 （.NET Standard 2.1 类库）
    /// </summary>
    public class AesGcmUtil
    {
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="data">明文</param>
        /// <param name="aesKey">key</param>
        /// <param name="associatedData">附加数据可能null</param>
        /// <returns>密文</returns>
        public static string Encrypt(string data, string aesKey, string associatedData = null)
        {
            byte[] key = Encoding.UTF8.GetBytes(aesKey);
            // 设置AesGcm实例
            using (var aesGcm = new AesCcm(key))
            {
                // 生成12字节的随机数
                byte[] nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
                RandomNumberGenerator.Fill(nonce);

                // 准备输入和输出数据缓冲区
                byte[] plaintext = Encoding.UTF8.GetBytes(data);
                byte[] ciphertext = new byte[plaintext.Length];
                byte[] tag = new byte[AesGcm.TagByteSizes.MaxSize];

                // 对输入数据进行加密
                aesGcm.Encrypt(nonce, plaintext, ciphertext, tag, Encoding.UTF8.GetBytes(associatedData));

                // 将随机数、密文、和tag合并为一个字节数组
                byte[] result = new byte[AesGcm.NonceByteSizes.MaxSize + ciphertext.Length + AesGcm.TagByteSizes.MaxSize];
                nonce.CopyTo(result, 0);
                ciphertext.CopyTo(result, AesGcm.NonceByteSizes.MaxSize);
                tag.CopyTo(result, AesGcm.NonceByteSizes.MaxSize + ciphertext.Length);
                return Convert.ToBase64String(result);
            }
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="data">密文</param>
        /// <param name="aesKey">key</param>
        /// <param name="associatedData">附加数据可能null</param>
        /// <returns>明文</returns>
        public static string Decrypt(string data, string aesKey, string associatedData = null)
        {
            byte[] key = Encoding.UTF8.GetBytes(aesKey);
            // 使用Base64解码将字符串转换为字节数组
            byte[] encryptedData = Convert.FromBase64String(data);

            // 提取密文、随机数和标签
            byte[] nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
            byte[] ciphertext = new byte[encryptedData.Length - AesGcm.NonceByteSizes.MaxSize - AesGcm.TagByteSizes.MaxSize];
            byte[] tag = new byte[AesGcm.TagByteSizes.MaxSize];
            Array.Copy(encryptedData, 0, nonce, 0, nonce.Length);
            Array.Copy(encryptedData, nonce.Length, ciphertext, 0, ciphertext.Length);
            Array.Copy(encryptedData, nonce.Length + ciphertext.Length, tag, 0, tag.Length);

            byte[] decryptedData = new byte[ciphertext.Length];

            // 使用关联数据和标签解密数据
            using (var aesGcm = new AesGcm(key))
            {
                aesGcm.Decrypt(nonce, ciphertext, tag, decryptedData, Encoding.UTF8.GetBytes(associatedData));
            }
            return Encoding.UTF8.GetString(decryptedData);
        }
    }
}
